package com.xyh.transaction.utils;

import com.xyh.transaction.common.Constant;
import io.jsonwebtoken.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;


/**
 * @author xiaoyh
 */
@Component
@Slf4j
public class JwtUtil {

    @Value("${jwt.secret}")
    private String secret;// jwt密钥

    public static void main(String[] args) {


        String token = new JwtUtil().generateJwtToken("123", "1");

        System.out.println(token);

        String t = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJsaW4tdXNlciIsImlhdCI6MTcwMjM2NDEyOCwiZXhwIjoxNzAyMzY0MTMzLCJ1c2VybmFtZSI6IjEyMyIsInVzZXJJZCI6IjEifQ.s420xSZIdSy0Ev_Dt6cebobjr-VXHJQXZKIBJvHVomc";

//        System.out.println(checkToken(t));
//        System.out.println(checkToken(t+1));
//
//
//        System.out.println(JwtUtil.decode(jwtToken.getJwtToken()));

    }

    /**
     * 生成token字符串的方法
     *
     * @param userName 用户名称
     * @param userId   用户id
     * @return token字符串
     */
    public String generateJwtToken(String userName, String userId) {
        // TODO jwtToken是否需要设置过期时间
        Date expireDate = new Date(System.currentTimeMillis() + Constant.JWT_EXPIRE_TIME);
        return Jwts.builder()
                //JWT头信息
                .setHeaderParam("typ", "JWT")
                .setHeaderParam("alg", "HS2256")
                //设置分类；设置过期时间 一个当前时间，一个加上设置的过期时间常量
                .setSubject("lin-user")
                .setIssuedAt(new Date())
                .setExpiration(expireDate)
                //设置token主体信息，存储用户信息
                .claim("username", userName)
                .claim("userId", userId)
                //.signWith(SignatureAlgorithm.ES256, SECRET)
                .signWith(SignatureAlgorithm.HS256, secret)
                .compact();
    }


    /**
     * 判断token是否存在与有效
     *
     * @param jwtToken token串
     * @return 验证结果
     */
    public String checkToken(String jwtToken) {
        if (StringUtils.isBlank(jwtToken)) {
            return Constant.ILLEGAL_TOKEN_DETAIL;
        }
        try {
            Jwts.parser().setSigningKey(secret).parseClaimsJws(jwtToken);
            // Token 验证通过，没有异常抛出
            return "";
        } catch (ExpiredJwtException e) {
            // JWT 已过期
            return Constant.EXPIRE_TOKEN_DETAIL;
        } catch (SignatureException e) {
            // JWT 签名验证失败
            return Constant.ILLEGAL_TOKEN_DETAIL;
        } catch (Exception e) {
            // 其他异常
            return Constant.OTHER_DETAIL;
        }
    }

    /**
     * 检查 Token 是否已过期
     *
     * @param token token字符串
     * @return true 如果 Token 已过期，false 否则
     */
    public boolean isTokenExpired(String token) {
        if (StringUtils.isEmpty(token)) {
            return true; // 如果 Token 为空，视为已过期
        }
        try {
            Claims claims = Jwts.parser()
                    .setSigningKey(secret)
                    .parseClaimsJws(token)
                    .getBody();
            Date expiration = claims.getExpiration();
            return expiration.before(new Date()); // 判断过期时间是否早于当前时间
        } catch (ExpiredJwtException e) {
            log.warn("Token 已过期: {}", e.getMessage());
            return true; // 捕获过期异常，返回已过期
        } catch (JwtException e) {
            log.error("解析 Token 出错: {}", e.getMessage(),e);
            return true; // 捕获其他异常，视为已过期
        }
    }


    /**
     * 判断token是否存在与有效
     *
     * @param request request
     * @return 验证结果
     */
    public boolean checkToken(HttpServletRequest request) {
        try {
            String token = request.getHeader("token");
            if (StringUtils.isBlank(token)) {
                return false;
            }
            Jwts.parser().setSigningKey(secret).parseClaimsJws(token);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    /**
     * 解密token
     *
     * @param request request
     * @return 解密结果map
     */
    public Map<String, String> getMemberIdByJwtToken(HttpServletRequest request) {
        String token = request.getHeader("token");
        return decode(token);
    }

    /**
     * 解密token
     *
     * @param token token字符串
     * @return 解密结果map
     */
    public Map<String, String> getMemberIdByJwtToken(String token) {
        return decode(token);
    }

    public Map<String, String> decode(String token) {
        // 封装解密结果
        Map<String, String> map = new HashMap<>();
        if (StringUtils.isEmpty(token)) {
            return map;
        }
        try {
            Jws<Claims> claimsJws = Jwts.parser()
                    .setSigningKey(secret)
                    .setAllowedClockSkewSeconds(Constant.JWT_EXPIRE_TIME / 1000) // 设置jwt过期时间的时钟偏差，
                    .parseClaimsJws(token);

            Claims body = claimsJws.getBody();
            String userName = (String) body.get("username");
            String userId = (String) body.get("userId");
            if (StringUtils.isBlank(userName)) {
                userName = "";
            }
            if (StringUtils.isBlank(userId)) {
                userId = "";
            }
            map.put("username", userName);
            map.put("userId", userId);
        } catch (JwtException e) {
            log.error("解析token时报错，错误信息：{}", e.getMessage(), e);
        }

        return map;
    }
}